home *** CD-ROM | disk | FTP | other *** search
/ ftp.cs.arizona.edu / ftp.cs.arizona.edu.tar / ftp.cs.arizona.edu / icon / newsgrp / group94a.txt / 000035_icon-group-sender _Sun Jan 30 18:38:28 1994.msg < prev    next >
Internet Message Format  |  1994-08-19  |  8KB

  1. Received: by cheltenham.cs.arizona.edu; Fri, 4 Feb 1994 09:22:47 MST
  2. Date: 30 Jan 94 18:38:28 GMT
  3. From: noc.near.net!news.delphi.com!usenet@uunet.uu.net  (Will Mengarini)
  4. Organization: Delphi (info@delphi.com email, 800-695-4005 voice)
  5. Subject: MS-DOS filename wildcard expander
  6. Message-Id: <19940130.13382812.mengarini@delphi.com>
  7. Sender: icon-group-request@cs.arizona.edu
  8. To: icon-group@cs.arizona.edu
  9. Status: R
  10. Errors-To: icon-group-errors@cs.arizona.edu
  11.  
  12. Goerwitz>> [...] MS-DOS is dying [...]
  13.  
  14. In reference to OS rwars, bear in mind that for people who only have
  15. toy computers, only toy OSs are realistic; but with serious hacking we
  16. can do serious work on these tiny machines. I can't program in real C++
  17. on my mighty 286/10; I think the compiles are too slow even on the 486/50
  18. I use at work. On the 286, tho, Icon works fine.
  19.  
  20. The following patch fixed a bug that looks to me like it should have made
  21. the procedure unusable; I can't understand how it could ever have worked
  22. as originally coded. I'd be interested in hearing from anybody who was able
  23. to successfully use it in its original form, with specifics about the
  24. compilers used to build Icon & the DOS version under which it ran. It'd be
  25. particularly interesting to hear an explanation of why it could have worked.
  26.  
  27. I suggest this replace the current version in BIPL.
  28.  
  29. ############################################################################
  30. #
  31. #  File:     dosfiles.icn
  32. #
  33. #  Subject:  Procedures to get MS-DOS file names
  34. #
  35. #  Author:   Paul Abrahams             Patched by:    Will Mengarini
  36. #
  37. #  Date:     September 24, 1990        Date:          We 20 Oct 93
  38. #
  39. ############################################################################
  40. #
  41. #  dosfiles(pfn) accepts a DOS filename possibly containing wildcards.
  42. #  The filename can also include a drive letter and path.
  43. #  If the filename ends in "\" or ":", "*.*" is appended.
  44. #
  45. #  The result sequence is a sequence of the filenames corresponding to pfn.
  46. #
  47. ############################################################################
  48. #
  49. #  Requires: MS-DOS extensions
  50. #
  51. ############################################################################
  52. #
  53. #  Patches:
  54. #
  55. #  We 20 Oct 93 Will Mengarini
  56. #     I tried dosfiles() using Icon 8.8 under MS-DOS 5.0.
  57. #     It always gave I/O Error 3, "Path not found".
  58. #     I'd built IconX & IconT using Borland C++ 3.1.
  59. #     -- The pointer arithmetic was wrong. My patches caused the
  60. #        code to work; they're flagged with "pointer arithmetic wrong: ".
  61. #       *The pointer arithmetic was coded based on a correct understanding
  62. #        that a 16-bit-mode far pointer (which is 32 bits, 16 each for
  63. #        segment & offset) resolves (in real mode) to a 20-bit physical
  64. #        address, formed by shifting the 16-bit segment left 1 nybble then
  65. #        taking the resulting 20-bit address & adding the 16-bit offset.
  66. #        However, on an Intel 80x86 processor this calculation is done in
  67. #        hardware; software should almost never do it. This is because
  68. #        calculation of a physical address in protected mode is completely
  69. #        different, with the segment being used as an index into a segment
  70. #        descriptor table; & this addressing difference needs to be
  71. #        transparent to most of the object code, so real-mode code can be
  72. #        relatively-painlessly converted into protected-mode code. Therefore,
  73. #        Intel 80x86 object code always passes around 16-bit-mode far
  74. #        pointers as 32-bit values, with the segment & offset each in a
  75. #        separate 16-bit register or memory "word" (which is what Intel calls
  76. #        what Real Computer people call a "halfword"), so when software must
  77. #        convert between a 16-bit-mode far pointer (which is 32 bits) & a
  78. #        pair of 16-bit segment & offset values, all 32 bits are significant;
  79. #        just plop the 16-bit segment into the upper half of the 32-bit area,
  80. #        or extract it from there. BTW, don't use expressions like
  81. #        integer_value / 32768 to get the upper 16 bits, since Icon will
  82. #        convert that to floating-point arithmetic; use
  83. #        ishift( integer_value, -16 ).
  84. #     -- The GetSpace() wasn't checked for failure, which could cause
  85. #        a null pointer reference.
  86. #     -- The GetSpace() had no FreeSpace(), so dosfiles() leaked memory.
  87. #     Possible enhancements:
  88. #     -- dosfiles() uses whatever the DTA was on entry. Therefore, multiple
  89. #        distinct searches can't be in progress simultaneously. Several times
  90. #        in professional C/C++ work I've needed that, for searching & also
  91. #        for file attribute retrieval (which is done using the same DOS
  92. #        call), & I've had to kluge because of runtime libraries that didn't
  93. #        support reentrant searching. It could be implemented by allocating
  94. #        space for a new DTA & storing the search data in that. However,
  95. #        every time the program suspends | returns, it must restore the
  96. #        default DTA to what it was on entry, in case some *other* process is
  97. #        using that DTA; then, on resumption, it must restore its own DTA
  98. #        pointer for its next outcome. FreeSpace() can be called on the
  99. #        allocated DTA after the final result has been produced.
  100. #       *IPD199.Doc warns that Icon expects its own internal allocations of
  101. #        memory blocks to result in contiguous memory, so it's not clear
  102. #        whether keeping a GetSpace() allocation around during a nontrivial
  103. #        amount of other processing is unsafe.
  104. #     -- Each time DOS returns a path name, it also returns all the other
  105. #        information about that file that DOS shows in a Dir or Attrib
  106. #        command. Somehow this should be accessible to the caller. To
  107. #        maintain backward compatibility, dosfiles() could take an optional
  108. #        2nd arg consisting of a string of letters each of which would
  109. #        correspond to one element of a returned list of data about the found
  110. #        file; for example, dosfiles("*.*", "psdta") would generate, for each
  111. #        match of *.*, a list consisting of the full path for the file, its
  112. #        size, its creation date, its creation time, & its attribute byte. As
  113. #        it does now, &null instead of a string would just mean "generate the
  114. #        names", & the results would be strings, not single-element lists
  115. #        containing strings (as would be produced by a second arg of "p").
  116. #
  117. ############################################################################
  118.  
  119. procedure dosfiles(pfn)
  120.    local asciiz, fnr, prefix, k, name
  121.    local ds, dx, result, fnloc, string_block
  122.  
  123. # Get Disk Transfer Address; filename locn is 30 beyond that.
  124.  
  125.    result := Int86([16r21, 16r2f00] ||| list(7,0))
  126.    # pointer arithmetic wrong: fnloc := 16 * result[8] + result[3]+ 30
  127.    fnloc := ishift( result[8], 16 ) + result[3] + 30
  128.  
  129. # Get the generalized filename.
  130.  
  131.    fnr := reverse(pfn)
  132.    k := upto("\\:", fnr) | *fnr + 1
  133.    prefix := reverse(fnr[k:0])
  134.    name := "" ~== reverse(fnr[1:k]) | "*.*"
  135.  
  136. # Get the first file in the sequence.
  137.  
  138.    asciiz := prefix || name || "\x00"
  139.    Poke(string_block := GetSpace(*asciiz), asciiz) |
  140.       stop( "dosfiles(): GetSpace() failed." )
  141.    # pointer arithmetic wrong: ds := string_block / 16
  142.    # pointer arithmetic wrong: dx := string_block % 16
  143.    ds := ishift( string_block, -16 )
  144.    dx := iand( string_block, 16rffff )
  145.    result := Int86([16r21, 16r4e00, 0, 0, dx, 0, 0, 0, ds])
  146.    FreeSpace(string_block)
  147.    case result[2] of {
  148.       0 : {}
  149.       18 : fail
  150.       default : stop("I/O Error ", result[2])
  151.       }
  152.    suspend prefix || extract_name(fnloc)
  153.  
  154. # Get the remaining files in the sequence.
  155.  
  156.    while Int86([16r21, 16r4f00, 0, 0, 0, 0, 0, 0, 0])[2] = 0 do
  157.       suspend prefix || extract_name(fnloc)
  158. end
  159.  
  160. procedure extract_name(fnloc)
  161.    local asciiz
  162.    asciiz := Peek(fnloc, 13)
  163.    return asciiz[1:upto("\x00", asciiz)]
  164. end
  165.